package com.kelab.dify.service;

import com.kelab.dify.config.DifyConfig;
import com.kelab.dify.exception.DifyException;
import com.kelab.dify.service.base.BaseService;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;

/**
 * 知识库服务类
 * 提供Knowledge Base API的所有功能
 * 
 * @author kelab
 * @version 1.0
 */
public class KnowledgeBaseService extends BaseService {
    
    private static final Logger logger = LoggerFactory.getLogger(KnowledgeBaseService.class);
    
    private static final String DATASETS_ENDPOINT = "datasets";
    private static final String DOCUMENTS_ENDPOINT = "documents";
    private static final String SEGMENTS_ENDPOINT = "segments";
    
    /**
     * 构造函数
     * 
     * @param httpClient HTTP客户端
     * @param objectMapper JSON映射器
     * @param config 配置信息
     */
    public KnowledgeBaseService(OkHttpClient httpClient, ObjectMapper objectMapper, DifyConfig config) {
        super(httpClient, objectMapper, config);
    }
    
    /**
     * 获取数据集列表
     * 
     * @param page 页码（可选）
     * @param limit 每页数量（可选）
     * @return 数据集列表响应
     * @throws DifyException 如果请求失败
     */
    public DatasetsResponse getDatasets(Integer page, Integer limit) throws DifyException {
        StringBuilder urlBuilder = new StringBuilder(config.getFullUrl(DATASETS_ENDPOINT));
        
        boolean hasParams = false;
        if (page != null && page > 0) {
            urlBuilder.append("?page=").append(page);
            hasParams = true;
        }
        if (limit != null && limit > 0) {
            urlBuilder.append(hasParams ? "&" : "?").append("limit=").append(limit);
        }
        
        Request request = new Request.Builder()
                .url(urlBuilder.toString())
                .get()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DatasetsResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to get datasets", e);
        }
    }
    
    /**
     * 创建数据集
     * 
     * @param name 数据集名称
     * @param description 数据集描述（可选）
     * @return 创建结果
     * @throws DifyException 如果请求失败
     */
    public DatasetResponse createDataset(String name, String description) throws DifyException {
        String json = String.format("{\"name\":\"%s\"", name);
        if (description != null && !description.isEmpty()) {
            json += String.format(",\"description\":\"%s\"", description);
        }
        json += "}";
        
        RequestBody body = RequestBody.create(json, JSON_MEDIA_TYPE);
        
        Request request = new Request.Builder()
                .url(config.getFullUrl(DATASETS_ENDPOINT))
                .post(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .addHeader("Content-Type", "application/json")
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DatasetResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to create dataset", e);
        }
    }
    
    /**
     * 获取数据集详情
     * 
     * @param datasetId 数据集ID
     * @return 数据集详情
     * @throws DifyException 如果请求失败
     */
    public DatasetResponse getDataset(String datasetId) throws DifyException {
        String url = config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId);
        
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DatasetResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to get dataset", e);
        }
    }
    
    /**
     * 更新数据集
     * 
     * @param datasetId 数据集ID
     * @param name 新名称（可选）
     * @param description 新描述（可选）
     * @return 更新结果
     * @throws DifyException 如果请求失败
     */
    public DatasetResponse updateDataset(String datasetId, String name, String description) throws DifyException {
        StringBuilder jsonBuilder = new StringBuilder("{");
        boolean hasFields = false;
        
        if (name != null && !name.isEmpty()) {
            jsonBuilder.append("\"name\":\"").append(name).append("\"");
            hasFields = true;
        }
        if (description != null && !description.isEmpty()) {
            if (hasFields) jsonBuilder.append(",");
            jsonBuilder.append("\"description\":\"").append(description).append("\"");
        }
        jsonBuilder.append("}");
        
        RequestBody body = RequestBody.create(jsonBuilder.toString(), JSON_MEDIA_TYPE);
        
        Request request = new Request.Builder()
                .url(config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId))
                .patch(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .addHeader("Content-Type", "application/json")
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DatasetResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to update dataset", e);
        }
    }
    
    /**
     * 删除数据集
     * 
     * @param datasetId 数据集ID
     * @return 删除结果
     * @throws DifyException 如果请求失败
     */
    public DeleteResponse deleteDataset(String datasetId) throws DifyException {
        String url = config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId);
        
        Request request = new Request.Builder()
                .url(url)
                .delete()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DeleteResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to delete dataset", e);
        }
    }
    
    /**
     * 获取文档列表
     * 
     * @param datasetId 数据集ID
     * @param keyword 搜索关键词（可选）
     * @param page 页码（可选）
     * @param limit 每页数量（可选）
     * @return 文档列表响应
     * @throws DifyException 如果请求失败
     */
    public DocumentsResponse getDocuments(String datasetId, String keyword, Integer page, Integer limit) throws DifyException {
        StringBuilder urlBuilder = new StringBuilder(config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId + "/" + DOCUMENTS_ENDPOINT));
        
        boolean hasParams = false;
        if (keyword != null && !keyword.isEmpty()) {
            urlBuilder.append("?keyword=").append(keyword);
            hasParams = true;
        }
        if (page != null && page > 0) {
            urlBuilder.append(hasParams ? "&" : "?").append("page=").append(page);
            hasParams = true;
        }
        if (limit != null && limit > 0) {
            urlBuilder.append(hasParams ? "&" : "?").append("limit=").append(limit);
        }
        
        Request request = new Request.Builder()
                .url(urlBuilder.toString())
                .get()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DocumentsResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to get documents", e);
        }
    }
    
    /**
     * 通过文本创建文档
     * 
     * @param datasetId 数据集ID
     * @param name 文档名称
     * @param text 文档内容
     * @param indexingTechnique 索引技术（可选）
     * @param processRule 处理规则（可选）
     * @return 创建结果
     * @throws DifyException 如果请求失败
     */
    public DocumentResponse createDocumentByText(String datasetId, String name, String text, 
                                               String indexingTechnique, Map<String, Object> processRule) throws DifyException {
        StringBuilder jsonBuilder = new StringBuilder();
        jsonBuilder.append("{");
        jsonBuilder.append("\"name\":\"").append(name).append("\",");
        jsonBuilder.append("\"text\":\"").append(text.replace("\"", "\\\"")).append("\"");
        
        if (indexingTechnique != null && !indexingTechnique.isEmpty()) {
            jsonBuilder.append(",\"indexing_technique\":\"").append(indexingTechnique).append("\"");
        }
        if (processRule != null && !processRule.isEmpty()) {
            jsonBuilder.append(",\"process_rule\":").append(toJson(processRule));
        }
        jsonBuilder.append("}");
        
        RequestBody body = RequestBody.create(jsonBuilder.toString(), JSON_MEDIA_TYPE);
        
        Request request = new Request.Builder()
                .url(config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId + "/" + DOCUMENTS_ENDPOINT))
                .post(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .addHeader("Content-Type", "application/json")
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DocumentResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to create document by text", e);
        }
    }
    
    /**
     * 通过文件创建文档
     * 
     * @param datasetId 数据集ID
     * @param file 文件
     * @param indexingTechnique 索引技术（可选）
     * @param processRule 处理规则（可选）
     * @return 创建结果
     * @throws DifyException 如果请求失败
     */
    public DocumentResponse createDocumentByFile(String datasetId, java.io.File file, 
                                               String indexingTechnique, Map<String, Object> processRule) throws DifyException {
        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(),
                        RequestBody.create(file, MediaType.parse("application/octet-stream")));
        
        if (indexingTechnique != null && !indexingTechnique.isEmpty()) {
            bodyBuilder.addFormDataPart("indexing_technique", indexingTechnique);
        }
        if (processRule != null && !processRule.isEmpty()) {
            bodyBuilder.addFormDataPart("process_rule", toJson(processRule));
        }
        
        RequestBody body = bodyBuilder.build();
        
        Request request = new Request.Builder()
                .url(config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId + "/" + DOCUMENTS_ENDPOINT))
                .post(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DocumentResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to create document by file", e);
        }
    }
    
    /**
     * 获取文档详情
     * 
     * @param datasetId 数据集ID
     * @param documentId 文档ID
     * @return 文档详情
     * @throws DifyException 如果请求失败
     */
    public DocumentResponse getDocument(String datasetId, String documentId) throws DifyException {
        String url = config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId + "/" + DOCUMENTS_ENDPOINT + "/" + documentId);
        
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DocumentResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to get document", e);
        }
    }
    
    /**
     * 删除文档
     * 
     * @param datasetId 数据集ID
     * @param documentId 文档ID
     * @return 删除结果
     * @throws DifyException 如果请求失败
     */
    public DeleteResponse deleteDocument(String datasetId, String documentId) throws DifyException {
        String url = config.getFullUrl(DATASETS_ENDPOINT + "/" + datasetId + "/" + DOCUMENTS_ENDPOINT + "/" + documentId);
        
        Request request = new Request.Builder()
                .url(url)
                .delete()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, DeleteResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to delete document", e);
        }
    }
    
    // 内部响应类定义
    public static class DatasetsResponse {
        // 根据实际API响应结构定义字段
    }
    
    public static class DatasetResponse {
        // 根据实际API响应结构定义字段
    }
    
    public static class DocumentsResponse {
        // 根据实际API响应结构定义字段
    }
    
    public static class DocumentResponse {
        // 根据实际API响应结构定义字段
    }
    
    public static class DeleteResponse {
        // 根据实际API响应结构定义字段
    }
}